package com.nexgo.payment.trans;

import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.nexgo.data.entity.RecvData;
import com.nexgo.data.json.JsonRecData;
import com.nexgo.data.json.JsonSendData;
import com.nexgo.data.json.JsonTools;
import com.nexgo.data.json.bean.JsonBody;
import com.nexgo.payment.App;
import com.nexgo.payment.BaseTransView;
import com.nexgo.payment.R;
import com.nexgo.payment.action.ActionResult;
import com.nexgo.payment.action.ActionStep;
import com.nexgo.payment.aop.annotation.RunOnMainThread;
import com.nexgo.payment.api.ApiLocationService;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.constrant.ResponseState;
import com.nexgo.payment.constrant.TransState;
import com.nexgo.payment.constrant.TransType;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.databases.TransRecord;
import com.nexgo.payment.databases.mapper.TransRecordMapper;
import com.nexgo.payment.entity.MessageData;
import com.nexgo.payment.util.ByteUtil;
import com.nexgo.payment.util.MessageHelper;
import com.nexgo.payment.util.StringUtils;
import com.nexgo.payment.util.TransUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 创建日期:2018/2/2 14:09
 * 创建人： wzp
 * @version
 * 修改人： wzp
 * 类说明;
 */
public abstract class AbsScanTransPresenter extends AbsOnlinePresenter{
    private final Logger mLog = LoggerFactory.getLogger(AbsScanTransPresenter.class.getSimpleName());

    private RecvData mRecvData;
    private boolean mIsFirstTime = true;
    //lr add
    private JsonRecData mJsonRecData;
    private ApiLocationService mLocationService;

    protected AbsScanTransPresenter(@NonNull BaseTransView view, @NonNull DataSource repository) {
        super(view, repository);
    }

    /**
     * 交易是否需要输入密码，如设置了撤销不用密码
     *
     * @return 是或否
     */
    private boolean isTransNeedPin() {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkFreePinBySetting()) {
                mLog.debug("交易设置为需要输入密码");
                return TransUtils.isTransNeedPin(mTransData.getTransType(), mRepository);
            }
        }
        return true;
    }

    /**
     * 交易判断是否走qps的免密流程
     *
     * @param pan    卡号
     * @param amount 金额
     * @return 是或否
     */
    private boolean isQpsFreePin(String pan, String amount) {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkQpsFreePin()) {
                mLog.debug("交易流程支持免密");
                return TransUtils.isQpsFreePin(pan, amount, mTransData.isCreditCard(), mRepository);
            }
        }
        return false;
    }

    /**
     * 交易判断是否走qps免签流程
     *
     * @param amount 金额
     * @return 是或否
     */
    private boolean isQpsFreeSignature(String amount) {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            if (transFlow.checkQpsFreeSignature()) {
                mLog.debug("交易流程支持免签");
                return TransUtils.isQpsFreeSignature(amount, mRepository);
            }
        }
        return false;
    }



    /**
     * 交易判断是否要发起打印单步骤
     *
     * @return 是或否
     */
    private boolean isNeedReceipt() {
        TransFlow transFlow = this.getClass().getAnnotation(TransFlow.class);
        if (transFlow != null) {
            boolean result = transFlow.checkNeedReceipt();
            if (result) {
                mLog.debug("交易流程支持打印签购单");
            }
            return result;
        } else {
            return true;
        }
    }


    /**
     * 扫码交易第二部查询
     *
     * @param recvData 响应数据
     */
    protected abstract void onTransQueryOrCancel(JsonRecData recvData);

    protected abstract void inputScanNext(Object scanData);

    protected abstract void inputTraceCodeNext(Object scanData);

 	protected abstract void onShowScanOrderUrl(JsonRecData recvData);

    protected abstract void showScanUrlNext();

    @Override
    @RunOnMainThread
    public void start() {
        if (mIsFirstTime) {
            mTransData = getTransData();

            onFirstAction();
            mIsFirstTime = false;
        }
    }


    @Override
    public void pause() {

    }

    @Override
    public void destroy() {
        cancelProcess();
    }

    @Override
    public void importActionResult(ActionResult actionResult) {
        Object data = actionResult.getData();
        ActionStep step = (ActionStep) actionResult.getAction().getActionStep();
        int ret = actionResult.getRet();
        mLog.debug("curr action step {} ret {}", step, actionResult.getRet());
        //特殊处理
        if (ret == ActionResult.ERR_CANCEL) {
            if(step.equals(ActionStep.ONLINE)) {
                onlineNext(false, null);
                return;
            }
            postMainThread(() -> mView.quitTrans());
            return;
        }
        if (ret == ActionResult.ERR_TIMEOUT) { // 超时 发查询
            if (step.equals(ActionStep.ONLINE)) {
                onlineNext(true, null);
                return;
            }
        }
        if (ret == ActionResult.ERR_FAIL) { //解包异常 或者 通讯异常了 发查询
            if (step.equals(ActionStep.ONLINE)) {
                onlineNext(true, null);
                return;
            }
        }
        //统一失败处理
        if (ret != ActionResult.SUCC ) {
            String tip = (String) data;
            if ( ret == ActionResult.ERR_TIMEOUT ) {
                postMainThread(() -> mView.showError(StringUtils.firstNonEmpty(tip, App.sContext.getString(R.string.trans_timeout))));
            } else {
                if (!TextUtils.isEmpty(tip)) {
                    postMainThread(() -> mView.showError(tip));
                } else {
                    postMainThread(() -> mView.showTransFailed());
                }
            }
            return;
        }
        //成功处理
        if (ret == ActionResult.SUCC) {
            switch (step) {
                case INPUT_AMOUNT:
                    inputAmountNext(data);
                    break;
                case INPUT_SCAN:
                    inputScanNext(data);
                    break;
                case INPUT_TRACE_CODE:
                    inputTraceCodeNext(data);
                    break;
                case ONLINE:
                    onlineNext(true, data);
                    break;
                case SHOW_QRCODE:
                    showScanUrlNext();
                    break;
                case PRINT_RECEIPT:
                    printReceiptNext(data);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 打印结束下一步动作
     *
     * @param data
     */
    protected void printReceiptNext(Object data) {
        onTransSuccess(mRecvData);
    }



    /**
     * 联机请求完下一步动作
     *
     * @param isConnected 是否已与后台交互
     * @param data
     */
    @Override
    protected void onlineNext(boolean isConnected, Object data) {
        MessageData messageData = (MessageData) data;
        //isConnected为false，说明无网络，此时未存包
        if (!isConnected) {
            postMainThread(() -> mView.showConnectFailed());
        } else {
            if (messageData == null) {
                //超时或接收失败等
                //扫码消费 扫码查询超时
                if(TransType.SCAN_SALE.equals(mTransData.getTransType())
                 ||TransType.SCAN_QUERY.equals(mTransData.getTransType())) {
                    transFinish(TransState.ERR_SCAN);
                }
                else{
                    transFinish(TransState.ERR_NETWORK);
                }
                return;
            }
            //lr add
            JsonRecData jsonRecData = messageData.getJsonRecData();
            JsonSendData jsonSendData = messageData.getJsonSendData();

            //第二层响应码判断 扫码交易放在check包里判断，无第三层判断
           /* if(!jsonRecData.getREQ_BODY().getResponseType().equals("N")){
                postMainThread(() -> mView.showTransFailed());
                return;
            }*/
            //解密加密Decrypt
            String str = jsonRecData.getREQ_BODY().getDECRYPT();
            if(str !=null) {
                mLog.debug("加密Decrypt = {}", str);
                try {
                    //xhj add
//                    String str1 = UnionApi.getInstance().DecryptData(2, jsonSendData.getREQ_HEAD().getTranscode(),
//                            jsonSendData.getREQ_HEAD().getMcht_id(), jsonSendData.getREQ_HEAD().getTerm_trans_time(), str);
                    String str1 = ByteUtil.CalcByWKey(str,true);
                    mLog.debug("解密Decrypt = {}", str1);
                    jsonRecData.getREQ_BODY().setDECRYPT("{" + str1 + "}");//解密出来的数据前后补{}

                } catch (Exception e) {
                    mLog.debug("处理接收数据失败");
                    postMainThread(() -> mView.showTransFailed());
                    e.printStackTrace();
                    return;
                }
            }
            mJsonRecData = jsonRecData;

            int keyIdx = Integer.parseInt(StringUtils.firstNonEmpty(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_INDEX), "0"));
            boolean isQuery = false ;
            if ( TransType.SCAN_QUERY.equals(mTransData.getTransType()) && mTransData.getIsAutoQuery()){ isQuery = true ;}
            ResponseState responseState = MessageHelper.checkScanResponse(messageData.getJsonSendData(), messageData.getJsonRecData(), keyIdx ,isQuery);
            switch (responseState) {
                case ERR_MAC:
                    transFinish(TransState.ERR_CALCMAC);
                    break;
                case SUCCESS:  //如果扫码交易成功
                    //lr
                    if(TransType.SCAN_ORDER.equals(mTransData.getTransType())){
                        transFinish(TransState.ERR_SCAN);
                    }
                    else{
                        transFinish(TransState.SUCCESS);}
                    break;
                case ERR_RESPONSE:  //不是 00 WW 直接退出
                    transFinish(TransState.ERR_RESPONSE);
                    break;
                case ERR_MESSAGE:  //48域返回码错
                    transFinish(TransState.ERR_QUERY);
                    break;
                case ERR_SCAN: //需要查询
                    transFinish(TransState.ERR_SCAN);
                    break;
                default:
                    transFinish(TransState.ERR_OTHER);
                    break;
            }
        }
    }

    /**
     * 交易结束总处理，包括了数据库的处理
     *
     * @param transState 交易状态
     */
    private void transFinish(TransState transState) {
        //lr add手动查询成功失败都要显示界面
        if(TransType.SCAN_QUERY.equals(mTransData.getTransType()) && !mTransData.getIsAutoQuery()) {
            if(TransState.SUCCESS.equals(transState) || TransState.ERR_SCAN.equals(transState) || TransState.ERR_QUERY.equals(transState)) {
                onScanTransSuccess(mJsonRecData);
                return;
            }

        }
        switch (transState) {
            case SUCCESS:  //扫码消费成功打单
                //lr
                if(TransType.SCAN_ORDER.equals(mTransData.getTransType())){
                    onShowScanOrderUrl(mJsonRecData);
                } else if(TransType.SCAN_VOID.equals(mTransData.getTransType())
                        || TransType.SCAN_CANCEL.equals(mTransData.getTransType())){
                    postMainThread(() -> mView.showTransFailed());
                }
                else {
                    mTransData.setSuccess(true);
                    mLog.debug("交易成功");
                    //扫码查询特殊查询
                    if(TransType.SCAN_QUERY.equals(mTransData.getTransType())){
                        if(mTransData.getTemporary().equals("1")) {
                            mTransData.setTransType(TransType.SCAN_ORDER);
                        }else if(mTransData.getTemporary().equals("0")){
                            mTransData.setTransType(TransType.SCAN_SALE);
                        }
                    }
                    //更新交易记录
                    updateLastRecord(mJsonRecData);
                    //判断是否需要电子签名
                    if (isNeedReceipt()) {
                        postMainThread(() -> mView.showPrintReceipt());
                    } else {
                        //返回交易数据
                        onScanTransSuccess(mJsonRecData);
                    }
                }
                break;
            default:
                mTransData.setSuccess(false);
                mLog.debug("交易失败 {}", transState);
                //如果是响应码错，那提示响应码错，否则提示交易失败
                switch (transState) {
//                    case ERR_RESPONSE:
//                        showRespCodeError(mJsonRecData.getRSP_HEAD().getERROR_CODE());
//                        break;
                    case ERR_SCAN:   // 48域返回要求查询
                        //lr
                        if(TransType.SCAN_ORDER.equals(mTransData.getTransType())){
                            onShowScanOrderUrl(mJsonRecData);
                        }else if(TransType.SCAN_CANCEL.equals(mTransData.getTransType())
                                || TransType.SCAN_VOID.equals(mTransData.getTransType())){
                            postMainThread(() -> mView.showTransFailed());
                        } else {
                            onTransQueryOrCancel(mJsonRecData);
                        }
                        break;
                    case ERR_QUERY:
                        JsonBody jsonBody = JsonTools.fromJson(mJsonRecData.getREQ_BODY().getDECRYPT(),JsonBody.class);
                        String str = MessageHelper.getScanStateCodeErrorInfo(jsonBody.getTxn_state());
                        postMainThread(() -> mView.showError(str));
                        break;
                    default:
                        if(mJsonRecData != null && mJsonRecData.getREQ_BODY() != null) {
                            String message=mJsonRecData.getREQ_BODY().getResponseMessage();
                            String msg=mJsonRecData.getREQ_BODY().getResponseMsg();
                            if (message != null) {
                                mLog.debug("errMessage = {}",message);
                                postMainThread(() -> mView.showError(message));
                            } else if(msg != null){
                                mLog.debug("errMessage = {}",msg);
                                postMainThread(() -> mView.showError(msg));
                            }else {
                                postMainThread(() -> mView.showError(App.sContext.getString(R.string.trans_err)));
                            }
                        }else{
                            postMainThread(() -> mView.showTransFailed());
                        }
                        break;
                }
                break;
        }
    }


    void onTransQueryfaild(String errString){
//        String errString = null;
        final String tip = errString;

        if (!TextUtils.isEmpty(errString)) {
            postMainThread(() -> mView.showError(tip));
        } else {
            postMainThread(() -> mView.showError(App.sContext.getString(R.string.trans_err)));
        }
    }

    /**
     *  主扫被扫下一步不同的动作调用不同
     *
     * @param
     */
    protected abstract void inputAmountNext(Object data) ;


    /**
     * 更新最后一条交易记录
     *
     * @param recvData
     */
    private void updateLastRecord(JsonRecData recvData) {
        if (mTransData.getTransType().isSaveRecord() || mTransData.getTransType().isReversal()) {
            TransRecord lastTransRecord = mRepository.getLastTransRecord();
            if (lastTransRecord != null) {
                mLog.debug("更新最后一笔交易记录，流水号{}", lastTransRecord.getTraceNum());
                mRepository.updateTransRecord(new TransRecordMapper().transform(mTransData, recvData, lastTransRecord));
                //更新原交易撤销标识，处理码前两位为20表示退货，包括撤销
                if (TransType.values()[lastTransRecord.getTransType()].getProcCode().startsWith("20")
                        && mTransData.isSuccess()) {
                    //判断源凭证号是否存在
                    String orgTraceNum = lastTransRecord.getOrgTraceNum();
                    if (!TextUtils.isEmpty(orgTraceNum)) {
                        TransRecord orgTransRecord = mRepository.queryTransRecord(orgTraceNum);
                        if (orgTransRecord != null && orgTransRecord.getIsSuccess()) {
                            //设置为已撤销
                            orgTransRecord.setIsVoid(true);
                            mRepository.updateTransRecord(orgTransRecord);
                        }
                    }
                }
            }
        }
    }

    /**
     * 让最后一条交易记录置为失败
     */
    private void makeLastRecordAsFail() {
        if (mTransData.getTransType().isSaveRecord() || mTransData.getTransType().isReversal()) {
            TransRecord lastTransRecord = mRepository.getLastTransRecord();
            if (lastTransRecord != null) {
                lastTransRecord.setIsSuccess(false);
                lastTransRecord.setIsNeedReversal(false);
                mRepository.updateTransRecord(lastTransRecord);
            }
        }
    }

    protected void onScanTransSuccess(JsonRecData jsonRecData){
        onTransSuccess(mRecvData);
    }

    /**
     * 获取用卡方式，22域
     *
     * @return
     */
    protected String getEntryMode() {
        String field = "0";
        switch (mTransData.getCardMode()) {
            case SCAN:
                field += "03";
                break;
            default:
                field += "01";
                break;
        }
        if (mTransData.getPin() != null) {
            field += "1";
        } else {
            field += "2";
        }
        return field;
    }
}
